﻿using App.IBLL;
using App.Model.MiddlewareModel;
using APP.DTO;
using APP.DTO.Const;
using DataService.Core.Json;
using DataService.Core.Log;
using DataService.Data;
using System.Diagnostics;
using System.Reflection.Emit;
using System.Text;

namespace App.Service.BaseFilter
{
    public class RequestResponseRecordMiddleware
    {
        private readonly RequestDelegate _next;
        //中间件是否正确处理 True: 正常 Flase:程序处理发生异常
        private bool IsSuccess { get; set; }
        private Exception MiddlewareEx { get; set; }
        public RequestResponseRecordMiddleware(RequestDelegate next)
        {
            _next = next;
        }
        public async Task Invoke(HttpContext context, IRequestResponseRecordBLL requestResponseRecordBLL)
        {
            Stopwatch stopwatch = new Stopwatch();
            try
            {
                stopwatch.Start();
                HttpRequest request = context.Request;
                string hostPath = context.Request.Path;
                string requestUrl = GetRoute(context);
                string queryFormate = GetQueryPara(context);
                string formFormate = "";
                string headerFormate = GetHeader(context);
                string responseContent = "";
                // 获取请求body内容
                string requestBodyData = "";
                string requestToken = GetHeaderKey(context);
                if (request.Method.ToLower().Equals("post"))
                {
                    formFormate = GetFormPara(context);
                    requestBodyData = GeyBodyData(context);
                }
                #region 获取响应数据
                var originalResponseStream = context.Response.Body;
                int statusCode = 200;
                try
                {
                    using (var ms = new MemoryStream())
                    {
                        ms.Position = 0;
                        context.Response.Body = ms;
                        await _next(context);//调用下一个中间件****重要
                        ms.Position = 0;
                        var responseReader = new StreamReader(ms);
                        responseContent = await responseReader.ReadToEndAsync();
                        if (MiddlewareMsgConst.MsgList.Any(x => x == responseContent))
                        {
                            throw new Exception(MiddlewareMsgConst.NoLogin);
                        }
                        var tempDogMsg = MiddlewareMsgConst.LoginMsgList.Find(x => responseContent.Contains(x));
                        if (!string.IsNullOrEmpty(tempDogMsg))
                        {
                            throw new Exception(responseContent);
                        }
                        ms.Position = 0;
                        await ms.CopyToAsync(originalResponseStream);
                        responseReader.Close();
                    }
                    IsSuccess = true;
                    statusCode = context.Response.StatusCode;
                }
                catch (Exception ex)
                {
                    statusCode = context.Response.StatusCode;
                    context.Response.ContentType = "text/plain;charset=utf-8";
                    string errorMsg = ex.Message;
                    if (ex.Message.Contains("未授权请求"))
                    {
                        statusCode = APICode.AuthorizationFailCode;
                    }
                    else if (ex.Message.Contains("参数异常"))
                    {
                        statusCode = APICode.BussinessFailCode;
                    }
                    else if (ex.Message.Contains("不被允许的请求"))
                    {
                        statusCode = APICode.RequestFailCode;
                    }
                    else if (ex.Message.Contains(MiddlewareMsgConst.Restprefix))
                    {
                        statusCode = APICode.RestAppStatusCode;
                        var tempArray = ex.Message.Split('_');
                        if (tempArray.Length > 1)
                        {
                            errorMsg = tempArray[1];
                        }
                    }
                    //else if (!MiddlewareMsgDTO.IsStartUp)
                    //{
                    //    errorMsg = "服务未启动,请联系管理员启动服务";
                    //    statusCode = APICode.RequestFailCode;
                    //}
                    else
                    {
                        errorMsg = string.IsNullOrEmpty(errorMsg) ? "未知异常，请联系管理员" : errorMsg;
                        statusCode = APICode.FailCode;
                    }
                    HandleResult handleResult = new HandleResult { StatusCode = statusCode, Msg = errorMsg };
                    string tempReponseResult = JsonHelper.ToJson(handleResult);
                    byte[] tempByte = Encoding.UTF8.GetBytes(tempReponseResult);
                    using (var ms = new MemoryStream())
                    {
                        ms.Position = 0;
                        ms.Write(tempByte, 0, tempByte.Length);
                        context.Response.Body = ms;
                        ms.Position = 0;
                        await ms.CopyToAsync(originalResponseStream);
                    }
                    responseContent = ex.StackTrace + "," + ex.Message;
                    TraceLog.WriteLine(ex.StackTrace.ToString() + "!!!!" + ex.Message.ToString(), "中间件捕捉异常");
                    MiddlewareEx = ex;
                    IsSuccess = false;
                }
                #endregion
                stopwatch.Stop();
                string ip = request.HttpContext.Connection.RemoteIpAddress.ToString();
                //添加记录
                Snowflake snowflake = new Snowflake();
                long redcordId = snowflake.NewId();
                string guid = redcordId.ToString();
                string tempDirname = "请求响应信息\\" + DateTime.Now.ToString("yyyyMMdd");
                if (formFormate.Length > 8000)
                {
                    TraceLog.WriteLine(formFormate, tempDirname, "ReqestPost_" + guid);
                    formFormate = "ReqestPost_" + guid + ".txt";
                }
                if (responseContent.Length > 8000)
                {
                    TraceLog.WriteLine(responseContent, tempDirname, "Reponse_" + guid);
                    responseContent = "Reponse_" + guid + ".txt";
                }
                if (requestBodyData.Length > 8000)
                {
                    TraceLog.WriteLine(requestBodyData, tempDirname, "ReqestBody_" + guid);
                    requestBodyData = "ReqestBody_" + guid + ".txt";
                }
                string otherPath = "/API/StatisticsInfo/GetSoftStatisticsInfo";
                if (otherPath.Equals(hostPath))
                {
                    //获取统计数据不作记录
                    return;
                }

                RequestRecord requestRecord = new RequestRecord()
                {
                    ID = redcordId,
                    RequestKey = requestToken,
                    VisitUrl = requestUrl,
                    VisitDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                    RequestGetMsg = queryFormate,
                    RequestPostMsg = formFormate,
                    RequestHeaderMsg = headerFormate,
                    MethodType = context.Request.Method,
                    ResponseContent = responseContent,
                    RequestBody = requestBodyData,
                    ReponseStatusCode = statusCode,
                    ConsumingTime = (int)stopwatch.ElapsedMilliseconds,
                    IP = ip
                };
                requestResponseRecordBLL.SetRequestRecord(requestRecord);
                if (!IsSuccess)
                {
                    throw MiddlewareEx;
                }
            }
            catch (Exception ex)
            {
                if (IsSuccess)
                {
                    TraceLog.WriteLine("请求记录发生异常：" + ex.StackTrace + "!!" + ex.Message);
                }
                throw ex;
            }
        }

        private string GetHeaderKey(HttpContext context)
        {
            try
            {
                context.Request.Headers.TryGetValue("Authorization", out Microsoft.Extensions.Primitives.StringValues authStr);
                return authStr;
            }
            catch (Exception ex)
            {
                TraceLog.WriteLine("获取令牌异常" + ex.Message);
                return "获取令牌异常" + ex.Message;
            }
        }
        ////获取表单参数
        private string GetFormPara(HttpContext context)
        {
            try
            {
                string postPara = "";
                if (context.Request.ContentType != "application/json" && context.Request.Form != null && context.Request.Form.Count > 0)
                {
                    postPara =JsonHelper.ToJson(context.Request.Form);
                }
                return postPara;
            }
            catch (Exception ex)
            {
                TraceLog.WriteLine("获取POST表单参数异常：" + ex.Message + "***" + context.Request.ContentType);
                return "获取POST表单参数异常" + ex.Message;
            }
        }
        ////获取Get请求参数
        private string GetQueryPara(HttpContext context)
        {
            try
            {
                return context.Request.QueryString.Value;
            }
            catch (Exception ex)
            {
                TraceLog.WriteLine("获取Get参数异常：" + ex.Message);
                return "获取Get参数异常" + ex.Message;
            }
            //if (context.Request.Query.Keys.Count == 0) return null;
            //Dictionary<string, object> dic = new Dictionary<string, object>();
            //foreach (var item in context.Request.Query.Keys)
            //{
            //    dic[item] = context.Request.Form[item];
            //}
            //return dic;
        }
        ////获取Header
        private string GetHeader(HttpContext context)
        {
            try
            {
                return JsonHelper.ToJson(context.Request.Headers);
            }
            catch (Exception ex)
            {
                return "获取Header异常" + ex.Message;
            }
            //if (context.Request.Headers.Count == 0) return null;
            //Dictionary<string, object> dic = new Dictionary<string, object>();
            //foreach (var item in context.Request.Headers)
            //{

            //    dic[item.Key] = item.Value;
            //}
            //return dic;
        }
        //获取路由参数
        private string GetRoute(HttpContext context)
        {
            return context.Request.Host + context.Request.Path;
        }
        private string GeyBodyData(HttpContext context)
        {
            try
            {
                string bodyContent = "";
                if (context.Request.ContentType == "application/json")
                {
                    //启用倒带
                    context.Request.EnableBuffering();
                    using (var reader = new StreamReader(context.Request.Body, encoding: System.Text.Encoding.UTF8, detectEncodingFromByteOrderMarks: false, leaveOpen: true))
                    {
                        bodyContent = reader.ReadToEndAsync().Result;
                        context.Request.Body.Position = 0;
                    }
                }
                return bodyContent;

            }
            catch (Exception ex)
            {
                TraceLog.WriteLine("获取请求body异常：" + ex.Message + "**" + ex.StackTrace.ToString());
                return "";
            }
        }
        private async Task<Dictionary<string, string>> GetRequestBodyData(HttpContext context)
        {
            Dictionary<string, string> dic = new Dictionary<string, string>();
            var reqOrigin = context.Request.Body;
            var resOrigin = context.Response.Body;
            string requestBodyFormate = "";
            string responsesFormate = "";
            try
            {
                using (var newReq = new MemoryStream())
                {
                    //替换request流
                    context.Request.Body = newReq;
                    using (var newRes = new MemoryStream())
                    {
                        //替换response流
                        context.Response.Body = newRes;
                        using (var reader = new StreamReader(reqOrigin))
                        {
                            //读取原始请求流的内容
                            requestBodyFormate = reader.ReadToEnd();

                        }
                        using (var writer = new StreamWriter(newReq))
                        {
                            writer.Write(requestBodyFormate);
                            writer.Flush();
                            newReq.Position = 0;
                            await _next(context);
                        }
                        using (var reader = new StreamReader(newRes))
                        {
                            newRes.Position = 0;
                            responsesFormate = reader.ReadToEnd();

                        }
                        using (var writer = new StreamWriter(resOrigin))
                        {
                            writer.Write(responsesFormate);
                        }
                    }
                }
            }
            finally
            {
                context.Request.Body = reqOrigin;
                context.Response.Body = resOrigin;
                dic["Reponse"] = requestBodyFormate;
                dic["Request"] = requestBodyFormate;
            }
            return dic;
        }
    }
}
